NO.204 计算质数 简单
思路一:暴力法 双层for循环。1.第一层循环遍历逐个判断[2,n)。2.第二层循环判断参数是否为素数。:
1 | public int countPrimes(int n){ |
时间复杂度:O(n^2)
可改进点:例如,12=2*6、12=3*4、12=sqrt(12)*sqrt(12)、12=4*3、12=62,可以观察到后面就是前面两个数反过来,说明查找可以整除12的因子时只需要找到“一半”的位置即可,如果前“一半”没有可以整除的因子,那么后“一半”也没有,这个临界点“一半”就是sqrt(12)。所以上述isPrime()方法的循环条件可以写为“i\i<n”即可,该方法时间复杂度降到了O(sqrt(n))。
思路二:厄拉多塞筛法 不难想象,所有质数的倍数都不是质数。例如,2是质数,2的倍数4、6、8、10、12。。。都不是质数;3是质数,3的倍数6、9、12、15。。。都不是质数;可以看一下维基百科中一个厄拉多塞筛的gif图:
这种方法大概就是“排除法”,每确定一个质数,就可以排除一批非质数,那么算法就可以这么写:
1 | public int countPrimes(int n){ |
上述算法还存在两处冗余:
- 在本题的暴利算法下说的:只需要判断到sqrt(n)即可。
- 例如,12不是质数,所以会被设置为false,但是12既是2的倍数,也是3的倍数,所以它被标记了两次。
解决上述两处冗余后的算法:
1 | public int countPrimes(int n){ |
厄尔拉塞筛法的时间复杂度:O(nloglogn)
本人菜鸟,有错误请告知,感激不尽!